package com.xiashitech.apiservice.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.xiashitech.apiservice.Constants.Operate;
import com.xiashitech.apiservice.config.AgentConfig;
import com.xiashitech.apiservice.config.AuthConfig;
import com.xiashitech.apiservice.dao.PassappMapper;
import com.xiashitech.apiservice.dao.PushHistoryMapper;
import com.xiashitech.apiservice.dao.model.AgentNode;
import com.xiashitech.apiservice.dao.model.Passapp;
import com.xiashitech.apiservice.dao.model.PushHistory;
import com.xiashitech.apiservice.dto.AgentIdentityDTO;
import com.xiashitech.apiservice.grpc.IncrementalCacheService;
import com.xiashitech.apiservice.service.IPushHistroyService;
import com.xiashitech.apiservice.service.IPushService;
import com.xiashitech.interfaces.agent.dto.AgentConfigDTO;
import com.xiashitech.interfaces.authservice.AuthService;
import com.xiashitech.interfaces.authservice.dto.AuthDTO;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor(onConstructor = @_(@Autowired))
public class PushServiceImpl implements IPushService {
    private final AgentConfig agentConfig;
    private final IncrementalCacheService incrementalCacheService;
    public final int pageSize = 1000;
    private static final Log log = LogFactory.get();
    private final IPushHistroyService pushHistroyService;
    @Autowired
    private AuthService authService;
    private final AuthConfig authConfig;
    private final PassappMapper passappMapper;
    private final PushHistoryMapper pushHistoryMapper;

    @Override
    public JSONObject damDiff(JSONArray oldArr, JSONArray newArr, String systemId,  int curUserPage, int groupUserPageSize) {
        JSONObject returnObj = new JSONObject();
        JSONArray changeArray = new JSONArray();
        JSONArray nextArr = new JSONArray();
        // AtomicInteger totalRows = new AtomicInteger();
        AtomicInteger pageTotal = new AtomicInteger(1);
        try {
            AgentConfigDTO.setConfig(BeanUtil.copyProperties(agentConfig, AgentConfigDTO.class));
            AgentConfigDTO agentConfig = AgentConfigDTO.getConfig();
            Map<String, String> systemAppCode = agentConfig.getSystemAppCode();
            String appCode = systemAppCode.get(systemId);
            Passapp passapp = passappMapper.selectTokenByCode(appCode).stream().findFirst().orElse(Passapp.builder().build());
       /* AuthDTO authDTO = AuthDTO.builder().systemId(systemId).userId("fktest").actionId("select")
                .databaseService("jshERP").databaseName("default").databaseSchema("jsh_erp")
                .appCode("jsh-erp").appSecret("0c46a2bf-be7b-4cf6-8f5a-cd802f70f677").iamBaseUrl(authConfig.getIamBaseUrl())
                .build();*/
            AuthDTO authDTO = AuthDTO.builder().systemId(systemId).iamBaseUrl(authConfig.getIamBaseUrl())
                    .build();
            //authDTO.setTableName("jsh_account");
            // authDTO.setActionId("select");
            // authDTO.setDatabaseName("default");
            // authDTO.setDatabaseService("jshERP");
            //authDTO.setTableName("jsh_account");
            // authDTO.setDatabaseSchema("jsh_erp");
            authDTO.setAppCode(appCode);
            //authDTO.setAppCode("jsh-erp");
            authDTO.setAppSecret(passapp.getAuth_token());
            // authDTO.setAppSecret("0c46a2bf-be7b-4cf6-8f5a-cd802f70f677");
            AtomicInteger j = new AtomicInteger();
            newArr.forEach(column -> {
                //System.out.println(j.getAndIncrement());
                if (!oldArr.contains(column)) {
                    System.out.println("damDiff newArr column " + column);
                    String[] dataInfoArr = column.toString().split("\\.");


                    //DAM部门下的CategoryId(应用ID)
                    String departmentCategoryId = dataInfoArr[0];
                    //DAM 部门ID
                    String departmentId = dataInfoArr[1];
                    //DAM部门名称
                    String departmentName = dataInfoArr[2];
                    String columnName = dataInfoArr[8];
                    String tableName = dataInfoArr[7];
                    //tableName ="jsh_user";
                    String databaseSchema = dataInfoArr[6];
                    String databaseName = dataInfoArr[5];
                    String databaseService = dataInfoArr[4];
                    String sqlType = dataInfoArr[9];
                    String groupId = dataInfoArr[3];
                    String status = dataInfoArr[10];
                    String paasDepartmentId = "";
                    //获取列权限
                    if (Operate.INSERT.name().equals(sqlType.toUpperCase()) || Operate.DELETE.name().equals(sqlType.toUpperCase())) {
                        return;
                    }
                    // authDTO.setUserId("@" + systemId);
                    // authDTO.setUserId("fktest");
                    authDTO.setTableName(tableName);
                    authDTO.setDatabaseService(databaseService);
                    authDTO.setDatabaseName(databaseName);
                    authDTO.setDatabaseSchema(databaseSchema);
                    authDTO.setActionId(sqlType);

                    String paasGroupListUrl = StrUtil.format(authConfig.getApiUrlForGetPaasGroupList(), "name", departmentName);
                    String paasGroupListJson = HttpUtil.get(paasGroupListUrl);
                    JSONArray paasGroupList = JSONUtil.parseObj(JSONUtil.parseObj(paasGroupListJson).get("data")).getJSONArray("results");

                    Iterator<Object> it = paasGroupList.iterator();
                    while (it.hasNext()) {
                        JSONObject jsonObj = (JSONObject) it.next();
                        if (departmentCategoryId.equals(jsonObj.get("category_id").toString())) {
                            paasDepartmentId = jsonObj.get("id").toString();
                        }
                    }
                    String url = StrUtil.format(authConfig.getApiUrlForGetGroupUserInfo(), paasDepartmentId, curUserPage, groupUserPageSize);
                    // String url = "http://192.168.0.54:8009/api/v2/departments/100/profiles/";
                    String groupUserInfoJson = HttpUtil.get(url);
                    JSONObject groupUserInfo = JSONUtil.parseObj(groupUserInfoJson);
                    JSONObject dataObj = JSONUtil.parseObj(groupUserInfo.get("data"));
                    JSONArray userList = JSONUtil.parseArray(dataObj.get("results"));
                    int userCount = dataObj.getInt("count");
                    // totalRows.addAndGet(userCount);
                    int curpageTotal = (int) Math.ceil((double) userCount / groupUserPageSize);
                    // returnObj.putOpt("pageTotal",pageTotal);
                    if (curUserPage < curpageTotal) {
                        if (pageTotal.get() < curpageTotal) {
                            pageTotal.set(curpageTotal);
                        }
                        returnObj.putOpt("nextPage", curUserPage + 1);
                        nextArr.add(column);
                    }
                    if (userList == null || userList.isEmpty()) {
                        log.info("damDiff groupId " + groupId + "url:" + url + "groupUserInfo " + groupUserInfo + "userList Null");
                    }
                    if (userList != null && userList.size() > 0) {
                        String finalTableName = tableName;
                        userList.forEach(user -> {
                            JSONObject columnObj = new JSONObject();
                            // columnObj.putOpt("groupId", groupId);
                            columnObj.putOpt("action", sqlType);
                            columnObj.putOpt("databaseService", databaseService);
                            columnObj.putOpt("databaseName", databaseName);
                            columnObj.putOpt("databaseSchema", databaseSchema);
                            columnObj.putOpt("tableName", finalTableName);
                            JSONObject userOjb = JSONUtil.parseObj(user);
                            String userInfo = userOjb.get("username").toString();
                            String userId = userInfo.substring(0, userInfo.indexOf("@"));
                            columnObj.putOpt("userId", userId);
                            authDTO.setUserId(userId + "@" + systemId);
                            //authDTO.setUserId("fktest");
                            //authDTO.setUserId("153@jsh-erp");
                            AuthDTO tabAuthResult = authService.verifyAuth(authDTO);
                            columnObj.putOpt("tabAuth", tabAuthResult.isAuth());
                            if (tabAuthResult.getResult() == null) {
                                columnObj.putOpt("tabAuthReason", "none");
                            } else {
                                columnObj.putOpt("tabAuthReason", tabAuthResult.getResult());
                            }
                            columnObj.putOpt("status", status);
                            if (!"null".equals(columnName)) {
                                columnObj.putOpt("columnName", columnName);
                            }
                            authDTO.setColumnName(columnName);
                            AuthDTO colAuthResult = authService.verifyAuth(authDTO);
                            columnObj.putOpt("colAuth", colAuthResult.isAuth());
                            if (colAuthResult.getResult() == null) {
                                columnObj.putOpt("colAuthReason", "none");
                            } else {
                                columnObj.putOpt("colAuthReason", colAuthResult.getResult());
                            }
                            changeArray.add(columnObj);
                        });
                    }
                }
                /*  ((JSONObject) column).forEach((key,value)->{});*/
            });

        } catch (Exception e) {
            e.printStackTrace();
        }
        returnObj.putOpt("page", curUserPage);
        if (curUserPage == 1) {
            returnObj.putOpt("pageTotal", pageTotal);
        }
        returnObj.putOpt("nextArr", nextArr);
        returnObj.putOpt("change", changeArray);
        return returnObj;
    }

    public JSONObject getGroupUserChangeDam(JSONArray damArr, String systemId, JSONObject userChange) {
        JSONObject returnObj = new JSONObject();
        JSONArray changeArray = new JSONArray();
        JSONArray nextArr = new JSONArray();
        int curUserPage = 1;
        // AtomicInteger totalRows = new AtomicInteger();
        AtomicInteger pageTotal = new AtomicInteger(1);
        try {
            AgentConfigDTO.setConfig(BeanUtil.copyProperties(agentConfig, AgentConfigDTO.class));
            AgentConfigDTO agentConfig = AgentConfigDTO.getConfig();
            Map<String, String> systemAppCode = agentConfig.getSystemAppCode();
            String appCode = systemAppCode.get(systemId);
            Passapp passapp = passappMapper.selectTokenByCode(appCode).stream().findFirst().orElse(Passapp.builder().build());
       /* AuthDTO authDTO = AuthDTO.builder().systemId(systemId).userId("fktest").actionId("select")
                .databaseService("jshERP").databaseName("default").databaseSchema("jsh_erp")
                .appCode("jsh-erp").appSecret("0c46a2bf-be7b-4cf6-8f5a-cd802f70f677").iamBaseUrl(authConfig.getIamBaseUrl())
                .build();*/
            AuthDTO authDTO = AuthDTO.builder().systemId(systemId).iamBaseUrl(authConfig.getIamBaseUrl())
                    .build();
            //authDTO.setTableName("jsh_account");
            // authDTO.setActionId("select");
            // authDTO.setDatabaseName("default");
            // authDTO.setDatabaseService("jshERP");
            //authDTO.setTableName("jsh_account");
            // authDTO.setDatabaseSchema("jsh_erp");
            authDTO.setAppCode(appCode);
            //authDTO.setAppCode("jsh-erp");
            authDTO.setAppSecret(passapp.getAuth_token());
            // authDTO.setAppSecret("0c46a2bf-be7b-4cf6-8f5a-cd802f70f677");
            AtomicInteger j = new AtomicInteger();
            damArr.forEach(column -> {
                //System.out.println(j.getAndIncrement());
                System.out.println("damDiff newArr column " + column);
                String[] dataInfoArr = column.toString().split("\\.");

                //DAM部门下的CategoryId(应用ID)
                String departmentCategoryId = dataInfoArr[0];
                //DAM 部门ID
                String departmentId = dataInfoArr[1];
                //DAM部门名称
                String departmentName = dataInfoArr[2];
                String columnName = dataInfoArr[8];
                String tableName = dataInfoArr[7];
                //tableName ="jsh_user";
                String databaseSchema = dataInfoArr[6];
                String databaseName = dataInfoArr[5];
                String databaseService = dataInfoArr[4];
                String sqlType = dataInfoArr[9];
                String groupId = dataInfoArr[3];
                String status = dataInfoArr[10];
                String paasDepartmentId = "";
                //获取列权限
                if (Operate.INSERT.name().equals(sqlType.toUpperCase()) || Operate.DELETE.name().equals(sqlType.toUpperCase())) {
                    return;
                }
                // authDTO.setUserId("@" + systemId);
                //authDTO.setUserId("fktest");
                authDTO.setTableName(tableName);
                authDTO.setDatabaseService(databaseService);
                authDTO.setDatabaseName(databaseName);
                authDTO.setDatabaseSchema(databaseSchema);
                authDTO.setActionId(sqlType);

                String paasGroupListUrl = StrUtil.format(authConfig.getApiUrlForGetPaasGroupList(), "name", departmentName);
                String paasGroupListJson = HttpUtil.get(paasGroupListUrl);
                JSONArray paasGroupList = JSONUtil.parseObj(JSONUtil.parseObj(paasGroupListJson).get("data")).getJSONArray("results");
                pageTotal.set(1);
                String finalTableName = tableName;

                JSONObject columnObj = new JSONObject();
                // columnObj.putOpt("groupId", groupId);
                columnObj.putOpt("action", sqlType);
                columnObj.putOpt("userAction",userChange.getStr("action"));
                columnObj.putOpt("databaseService", databaseService);
                columnObj.putOpt("databaseName", databaseName);
                columnObj.putOpt("databaseSchema", databaseSchema);
                columnObj.putOpt("tableName", finalTableName);
                String userId = userChange.getStr("userId");
                columnObj.putOpt("userId", userId);
                authDTO.setUserId(userId + "@" + systemId);
                //authDTO.setUserId("fktest");
                //authDTO.setUserId("153@jsh-erp");
                AuthDTO tabAuthResult = authService.verifyAuth(authDTO);
                columnObj.putOpt("tabAuth", tabAuthResult.isAuth());
                if (tabAuthResult.getResult() == null) {
                    columnObj.putOpt("tabAuthReason", "none");
                } else {
                    columnObj.putOpt("tabAuthReason", tabAuthResult.getResult());
                }
                columnObj.putOpt("status", status);
                if (!"null".equals(columnName)) {
                    columnObj.putOpt("columnName", columnName);
                }
                authDTO.setColumnName(columnName);
                AuthDTO colAuthResult = authService.verifyAuth(authDTO);
                columnObj.putOpt("colAuth", colAuthResult.isAuth());
                if (colAuthResult.getResult() == null) {
                    columnObj.putOpt("colAuthReason", "none");
                } else {
                    columnObj.putOpt("colAuthReason", colAuthResult.getResult());
                }
                changeArray.add(columnObj);

                /*  ((JSONObject) column).forEach((key,value)->{});*/
            });

        } catch (Exception e) {
            e.printStackTrace();
        }
        returnObj.putOpt("page", curUserPage);
        if (curUserPage == 1) {
            returnObj.putOpt("pageTotal", pageTotal);
        }
        returnObj.putOpt("nextArr", nextArr);
        returnObj.putOpt("change", changeArray);
        return returnObj;

    }

    @Override
    public JSONObject getDamInitContent(PushHistory pushHistory, boolean pushFlag) {
        String data = "{\n" +
                "    \"pushKey\":\"damPermissionInit\",\n" +
                "    \"system_id\":\"jsh-erp\",\n" +
                "    \"new\":[\n" +
                "        \"48.346.jshERP.default.jsh_erp.jsh_account.null.select.1\",\n" +
                "        \"48.346.jshERP.default.jsh_erp.jsh_account.name.select.1\",\n" +
                "        \"48.346.jshERP.default.jsh_erp.jsh_account.code.select.1\"\n" +
                "    ]\n" +
                "}";
        String systemId = pushHistory.getSystemId();
        JSONArray returnArr = new JSONArray();
        JSONObject damObj = new JSONObject();
        damObj.putOpt("pushKey", "damPermissionInit");
        damObj.putOpt("systemId", systemId);
        damObj.putOpt("serviceId", pushHistory.getServiceId());
        damObj.putOpt("serialId", pushHistory.getSerialId());

        // damObj.putOpt("pageTotal", (int) Math.ceil((double) damFullResultArr.size() / pageSize));
        // damObj.putOpt("pageSize", pageSize);
        // damObj.putOpt("totalRows", damFullResultArr.size());
        // systemId = (JSONUtil.parseObj(data)).get("system_id").toString();
        String url = StrUtil.format(authConfig.getApiUrlForGetFullDamInfo(), systemId);
        String json = HttpUtil.get(url);
        // json = "{\"data\":[\n" +
        //      "{\"id\":349,\"name\":\"jsh-erp__财务经理\",\"iam\":[\"118.14603.财务经理.349.jsh-erp.default.jsh_erp.jsh_depot_head.account_id.select.1\",\"118.14603.财务经理.349.jsh-erp.default.jsh_erp.jsh_depot_head.sales_man.select.1\"]}\n" +
        //      ",{\"id\":348,\"name\":\"jsh-erp__财务经理\",\"iam\":[\"118.14600.总经理.348.jsh-erp.default.jsh_erp.jsh_depot_head.number.update.1\"]}]}";
        JSONArray damFullArr = JSONUtil.parseArray((JSONUtil.parseObj(json)).get("data"));
        AgentNode agentNode = new AgentNode();
        agentNode.setSystemId(systemId);
        agentNode.setServiceId(pushHistory.getServiceId());
        agentNode.setSerialId(pushHistory.getSerialId());
        List<AgentNode> agentNodeList = new ArrayList<>();
        agentNodeList.add(agentNode);
        JSONArray mergeIamArr = new JSONArray();
        for (int i = 0; i < damFullArr.size(); i++) {

            JSONArray newArr = JSONUtil.parseObj(damFullArr.get(i)).getJSONArray("iam");
            mergeIamArr.addAll(newArr);
        }
        int curPage = 1;
        JSONObject damDiffObj = damDiff(new JSONArray(), mergeIamArr, systemId,  curPage, pageSize);
        //int pageTotal = damDiffObj.getInt("pageTotal");
        if (pushFlag == true) {
            int j = 1;
            damDiffObj.putOpt("systemId", systemId);
            damDiffObj.putOpt("pushKey", "damPermissionInit");
            damDiffObj.putOpt("page", curPage);
            damDiffObj.putOpt("pageSize", pageSize);
            int pageTotal = damDiffObj.getInt("pageTotal");
            //  damDiffObj.putOpt("change", damDiffObj.get("pushArr"));
            damDiffObj.putOpt("pageTotal", pageTotal);
            pushToNode(systemId, agentNodeList, damDiffObj);
            System.out.println("damInit " + j);
            while (curPage < pageTotal) {
                j++;
                curPage++;
                damDiffObj = damDiff(new JSONArray(), damDiffObj.getJSONArray("nextArr"), systemId,  curPage, pageSize);
                damDiffObj.putOpt("systemId", systemId);
                damDiffObj.putOpt("pushKey", "damPermissionInit");
                damDiffObj.putOpt("page", curPage);
                damDiffObj.putOpt("pageSize", pageSize);
                damDiffObj.putOpt("pageTotal", pageTotal);
                damDiffObj.putOpt("change", damDiffObj.get("change"));
                pushToNode(systemId, agentNodeList, damDiffObj);
                System.out.println("damInit " + j);
            }

        }
        //damObj.putOpt("change", returnArr);

        return damObj;
    }

    public void pushToNode(String systemId, List<AgentNode> agentNodeList, JSONObject changeObj) {
        agentNodeList.forEach(node -> {
            System.out.println("pushToNode node, getSystemId: " + node.getSystemId()+", getServiceId: " + node.getServiceId() + ", getSerialId: " + node.getSerialId());
            JSONObject pushObj = null;
            try {
                pushObj = changeObj.clone();
            } catch (CloneNotSupportedException e) {
                throw new RuntimeException(e);
            }
            pushObj.remove("nextArr");
            PushHistory pushHistory = new PushHistory();

            // changeObj.remove("nextArr");
            pushObj.putOpt("systemId", systemId);
            pushObj.putOpt("serviceId", node.getServiceId());
            pushObj.putOpt("serialId", node.getSerialId());
            pushHistory.setContent(JSONUtil.toJsonStr(pushObj));
            pushHistory.setSystemId(systemId);
            pushHistory.setServiceId(node.getServiceId());
            pushHistory.setSerialId(node.getSerialId());
            pushHistory.setStatus(0);
            System.out.println("pushToNode insertHistory before, " + node.getSystemId()+"-" + node.getServiceId()+"-"+node.getSerialId());
            pushHistroyService.insertPushHistroy(pushHistory);
            System.out.println("pushToNode insertHistory after , " + node.getSystemId()+"-" + node.getServiceId()+"-"+node.getSerialId() + ", pushId: " + pushHistory.getId());
            pushObj.putOpt("pushId", pushHistory.getId());
            String pushString = JSONUtil.toJsonStr(pushObj);
            // 这几行好像也没用？看是否注释掉 TODO
            AgentIdentityDTO agentIdentityDTO = AgentIdentityDTO.builder().build();
            agentIdentityDTO.setSystemId(systemId);
            agentIdentityDTO.setServiceId(node.getServiceId());
            agentIdentityDTO.setSerialId(node.getSerialId());
            List<AgentIdentityDTO> currentAgentNodeList = incrementalCacheService.getAgentIds(systemId);
            currentAgentNodeList.stream().map(AgentIdentityDTO::getSystemId).collect(Collectors.toList());
            incrementalCacheService.pushIncrementToClient(systemId, node.getServiceId(), node.getSerialId(), pushString);
            System.out.println("pushToNode result pushString execute: " + pushString);

        });
    }

    @Override
    public JSONObject getDesensitizationInitContent(PushHistory pushHistory) {
        String systemId = pushHistory.getSystemId();
        JSONObject desensitizationObj = new JSONObject();
        String authUrl = StrUtil.format(authConfig.getApiUrlForAllAuthDesense(), systemId);
        System.out.println("authConfig " + authConfig);
        log.info("authConfig " + authConfig);
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("systemId", systemId);
        System.out.println("authUrl " + authUrl);
        log.info("authUrl " + authUrl);
        String desensitizationResponse = HttpUtil.get(authUrl);
        PushHistory desensitizationPushHistory = new PushHistory();
        desensitizationObj.putOpt("pushKey", "desensitizationInit");
        desensitizationObj.putOpt("systemId", systemId);
        desensitizationObj.putOpt("serviceId", pushHistory.getServiceId());
        desensitizationObj.putOpt("serialId", pushHistory.getSerialId());
        desensitizationObj.putOpt("change", (JSONUtil.parseObj(desensitizationResponse)).get("change"));
        desensitizationPushHistory.setContent(JSONUtil.toJsonStr(desensitizationObj));
        desensitizationPushHistory.setSystemId(systemId);
        desensitizationPushHistory.setServiceId(pushHistory.getServiceId());
        desensitizationPushHistory.setSerialId(pushHistory.getSerialId());
        desensitizationPushHistory.setStatus(0);
        pushHistroyService.insertPushHistroy(desensitizationPushHistory);
        desensitizationObj.putOpt("pushId", desensitizationPushHistory.getId());
        System.out.println("desensitizationPushHistory " + desensitizationPushHistory.getId());
        return desensitizationObj;
    }

}
